﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FCS;

namespace Applications
{
    public class Queens : BaseCaseListFunc<IFunList<int>>
    {
        public Queens(int n) : this(n, n) { }

        // queens 0 = [[]]
        // queens n = [ [q:b] \\ b <- queens (n-1),
        //          q <- [0..7] | safe q b ]
        protected Queens(int n, int maxdim)
        {
            Case(() => n == 0, () => EmptyLL<int>());
            Case(() => true, () => MapL2L(
                                b => ConsL(
                                    Filter(q => SafeOpt(q, b), IntList(0, maxdim - 1)), b),
                                        new Queens(n - 1, maxdim)));
        }

        // safeOpt q b = and [not (checksOpt q b!!i i)
        //                     \\ i <- [0 .. (length b)-1] ]
        static Func<int, IFunList<int>, bool> SafeOpt =
            (q, b) => And((bi, i) => !ChecksOpt(q, bi, i), b);

        // checksOpt q bi i = (q == bi) || (abs(q-bi)==(i+1))
        static Func<int, int, int, bool> ChecksOpt =
            (q, bi, i) => (q == bi || Math.Abs(q - bi) == i + 1);

        //// safe q b = and [not (checks q b i)
        ////                     \\ i <- [0 .. (length b)-1] ]
        //static Func<int, IFunList<int>, bool> Safe =
        //    (q, b) => And(Map<int, bool>(i => !Checks(q, b, i), IntList(0, b.Count() - 1)));

        //// checks q b i = (q == b!!i) || (abs(q-b!!i)==(i+1))
        //static Func<int, IFunList<int>, int, bool> Checks =
        //    (q, b, i) => (q == At(i, b) || Math.Abs(q - At(i, b)) == i + 1);
    }
}
